package com.ape.mapsa.common;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.faces.application.ConfigurableNavigationHandler;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;
import org.primefaces.context.RequestContext;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.MenuModel;

import com.ape.mapsa.common.constants.Periodo;
import com.ape.mapsa.common.constants.TipoMaterial;
import com.ape.mapsa.produccion.model.Cliente;
import com.ape.mapsa.produccion.model.Color;
import com.ape.mapsa.produccion.model.DepItemPrintSpec;
import com.ape.mapsa.produccion.model.EstadoProduccion;
import com.ape.mapsa.produccion.model.Item;
import com.ape.mapsa.produccion.model.Muestra;
import com.ape.mapsa.produccion.model.OrdenProduccion;
import com.ape.mapsa.produccion.model.PedidoVenta;
import com.ape.mapsa.produccion.service.IProduccionService;

@ManagedBean(name = "ordenVtaMB")
@ViewScoped
public class OrdenVentasBean extends BeanCRUD implements Serializable {

	private static final long serialVersionUID = 9203666218887841128L;

	private static final Logger log = Logger.getLogger(OrdenVentasBean.class);

	@ManagedProperty(value = "#{produccionService}")
	private IProduccionService produccionService;

	@ManagedProperty(value = "#{itemsMB}")
	private ItemsBean itemBean;

	@ManagedProperty(value = "#{clientesMB}")
	private ClienteBean clienteBean;

	@ManagedProperty(value = "#{muestrasMB}")
	private MuestrasBean muestraBean;

	@ManagedProperty(value = "#{colorsMB}")
	private ColorsBean colorsBean;

	@ManagedProperty(value = "#{userMB}")
	private UserBean userBean;

	private List<OrdenProduccion> filteredOrdenProds;
	private List<OrdenProduccion> ordenesProd;

	private OrdenProduccion selectedOp;
	private EstadoProduccion estadoFiltro;
	private OrdenProduccion newOrden;
	private List<Color> colores;

	private TipoMaterial[] tiposMaterial;
	private TipoMaterial tipoMaterialSeleccionado;

	private Periodo periodo = Periodo.ULTIMOS_7_DIAS;
	private Periodo[] periodos = Periodo.values();

	private Item selectedItem;
	private String state;
	private Date currentDate = new Date();

	private boolean addingItemToSalesOrder;

	@PostConstruct
	public void initialize() {
		log.info("Initializing OrdenVentasBenan");
		selectedOp = null;
		HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
		state = request.getParameter("state");
		Long stateL = null;
		if (state != null && !state.isEmpty()) {
			stateL = Long.valueOf(state);
			setEstadoFiltro(produccionService.getEstadoProduccionById(stateL));
		}

		ordenesProd = produccionService.getOrdenProdByState(stateL);

		filteredOrdenProds = new ArrayList<OrdenProduccion>();
		filteredOrdenProds.addAll(ordenesProd);

		String ordenProdId = request.getParameter("salesOrder");
		if (ordenProdId != null) {

			newOrden = produccionService.getOpById(Long.valueOf(ordenProdId));
			log.debug("adding item to sales order: " + newOrden.getPedidoVenta().getId());
			newOrden.setItem(new Item());
			newOrden.setCantidad(0);
			newOrden.setObservacion(null);
			newOrden.setPrioridad(0);
			addingItemToSalesOrder = true;
		} else {
			newOrden = new OrdenProduccion();
			Long nextId = produccionService.getPedidVentaNextId();
			log.debug("Next id: " + nextId);
			newOrden.getPedidoVenta().setId(nextId);
		}
		newOrden.getItem().setDepItemPrintSpec(new DepItemPrintSpec());
		colores = produccionService.getAllColors();
		setTiposMaterial(TipoMaterial.values());
		initilizeSubmenu();
	}

	public void handlePeriodoChange() {
		log.debug("Periodo " + periodo);
	}

	private void initilizeSubmenu() {
	}

	public void rowSelected(SelectEvent event) {
		log.info("Orden de prod seleccionado " + selectedOp.getId());
	}

	public void rowUnselected(SelectEvent event) {
		log.info("Orden de prod deseleccionado ");
	}

	public void addNewItem(ActionEvent event) {
		itemBean.addNewItem(event);
		newOrden.setItem(itemBean.getNewItem());
	}

	public void addArticuloToSales(ActionEvent event) {
		if (selectedOp != null) {
			log.info("Pedido Nuevo");
			FacesContext context = FacesContext.getCurrentInstance();
			ConfigurableNavigationHandler handler = (ConfigurableNavigationHandler) context.getApplication().getNavigationHandler();
			setAddingItemToSalesOrder(true);
			handler.performNavigation("addPedidoVenta?faces-redirect=true&salesOrder=" + selectedOp.getId());
		} else {
			FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_WARN, "Advertencia: ", "Debe seleccionar un pedido para agergar mas articulos");
			FacesContext.getCurrentInstance().addMessage(null, msg);
			RequestContext reqContext = RequestContext.getCurrentInstance();
			reqContext.update("dataForm:dataGrowl");
		}
	}

	@Override
	public void save(ActionEvent event) {
		log.info("Adding new sales order");
		try {
			// VALIDACION
			RequestContext requestContext = RequestContext.getCurrentInstance();
			Color prodColor = produccionService.getColorByDescription(newOrden.getItem().getColorBean());
			if (prodColor == null) {
				FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Color inexistente", newOrden.getItem().getColorBean()
						.getDescripcion());
				FacesContext.getCurrentInstance().addMessage(null, msg);
				requestContext.addCallbackParam("isValid", false);
			}
			newOrden.getItem().setColorBean(prodColor);
			newOrden.setEstadoProduccion(produccionService.getProdStateById(1L));

			if (!newOrden.getFechaEntrega().after(new Date())) {
				requestContext.addCallbackParam("isValid", false);
				FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_WARN, "Cuidado:",
						"La fecha de entrega no puede ser antes o igual a la de hoy");
				FacesContext.getCurrentInstance().addMessage(null, msg);
			}

			if (!valiateCliente()) {
				requestContext.addCallbackParam("isValid", false);
			}

			if (requestContext.getCallbackParams().get("isValid") != null && !((boolean) requestContext.getCallbackParams().get("isValid"))) {
				requestContext.scrollTo("dialogForm:growl");
				return;
			}

			log.debug("Getting peiddo de venta con id: " + newOrden.getPedidoVenta().getId());
			PedidoVenta pedidoVenta = produccionService.getPedidoById(newOrden.getPedidoVenta().getId());

			if (pedidoVenta != null) {
				log.debug("pedido de venta encontrado");
				newOrden.setPedidoVenta(pedidoVenta);
			} else {
				log.debug("pedido no encontrado, guardando uno nuevo con id " + newOrden.getPedidoVenta().getId());
				pedidoVenta = produccionService.savePedidoVenta(newOrden.getPedidoVenta());
				newOrden.setPedidoVenta(pedidoVenta);
			}
			String userEmail = FacesContext.getCurrentInstance().getExternalContext().getRemoteUser();
			log.info("USUARIO: " + userEmail);

			produccionService.addOp(newOrden, userEmail, userBean.getUserId());
			ordenesProd.add(newOrden);
			filteredOrdenProds.add(newOrden);
			FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Se agrego la orden de venta", newOrden.getId().toString());
			FacesContext.getCurrentInstance().addMessage(null, msg);

			FacesContext context = FacesContext.getCurrentInstance();
			ConfigurableNavigationHandler handler = (ConfigurableNavigationHandler) context.getApplication().getNavigationHandler();
			handler.handleNavigation(context, "pedidoAgregado", "pedidosVenta?faces-redirect=true");
		} catch (Exception x) {
			x.printStackTrace();
			log.error(x);
			FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Falla para agregar Orden de venta ", x.getMessage());
			FacesContext.getCurrentInstance().addMessage(null, msg);
		}
	}

	@Override
	public void update(ActionEvent event) {
		log.info("Actualizando ordens de venta");
	}

	@Override
	public void create(ActionEvent event) {
		log.info("Pedido Nuevo");
		FacesContext context = FacesContext.getCurrentInstance();
		ConfigurableNavigationHandler handler = (ConfigurableNavigationHandler) context.getApplication().getNavigationHandler();
		handler.performNavigation("addPedidoVenta?faces-redirect=true");
	}

	@Override
	public void edit(ActionEvent event) {

	}

	@Override
	public void delete(ActionEvent event) {
		// TODO Auto-generated method stub

	}

	public List<Color> completeColores(String query) {
		List<Color> results = new ArrayList<Color>();
		for (Color color : colores) {
			if (color.getDescripcion().contains(query)) {
				results.add(color);
			}
		}
		return results;
	}

	public List<String> completeOrdenVenta(String query) {
		List<String> results = new ArrayList<String>();
		for (OrdenProduccion orden : ordenesProd) {
			String nroPedido = orden.getPedidoVenta().getId().toString();
			if (!results.contains(nroPedido) && nroPedido.contains(query)) {
				results.add(nroPedido);
			}
		}
		return results;
	}

	public void updateNewItem() {
		log.debug("Item: " + itemBean.getNewItem());
		log.debug("Print specs: " + itemBean.getNewItem().getDepItemPrintSpec());
		if (!itemBean.isNewItemDuplicado()) {
			newOrden.setItem(itemBean.getNewItem());
		}
	}

	public boolean valiateCliente() {
		log.info("VALIDANDO CLIENTE");
		// TODO: Esto no esta validando bien.
		String nombreClie = newOrden.getPedidoVenta().getClienteBean().getNombre();
		if (newOrden.getPedidoVenta() != null && newOrden.getPedidoVenta().getClienteBean() != null && !nombreClie.trim().equals("")) {
			for (OrdenProduccion ordenProd : ordenesProd) {
				Long pedidoNumero = newOrden.getPedidoVenta().getId();
				if (ordenProd.getPedidoVenta().getId().equals(pedidoNumero)
						&& !ordenProd.getPedidoVenta().getClienteBean().getNombre().equals(nombreClie)) {
					FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_WARN, "Cliente erroneo", "El cliente \"" + nombreClie
							+ "\" no corresponde con el cliente \"" + ordenProd.getPedidoVenta().getClienteBean().getNombre()
							+ "\" del pedido de venta Numero: \"" + pedidoNumero + "\"");
					FacesContext.getCurrentInstance().addMessage(null, message);
					return false;
				}
			}
		}
		return true;
	}

	public void actualizarPedido(SelectEvent event) {
		String pedidoNro = event.getObject().toString();
		for (OrdenProduccion orden : ordenesProd) {
			if (orden.getPedidoVenta().getId().toString().equals(pedidoNro)) {
				PedidoVenta pedido = new PedidoVenta();
				Cliente clienteBean2 = new Cliente();
				clienteBean2.setId(orden.getPedidoVenta().getClienteBean().getId());
				clienteBean2.setNombre(orden.getPedidoVenta().getClienteBean().getNombre());
				clienteBean2.setNumero(orden.getPedidoVenta().getClienteBean().getNumero());
				pedido.setClienteBean(clienteBean2);
				pedido.setId(orden.getId());
				pedido.setId(orden.getPedidoVenta().getId());
				newOrden.setPedidoVenta(pedido);
				break;
			}
		}
	}

	public void getResultItem(ActionEvent actionEvent) {
		log.info("Getting result from item" + itemBean.getResult());
		newOrden.setItem(itemBean.getResult());
	}

	public void getResultMuestra() {
		Muestra muestraRes = muestraBean.getResult();
		newOrden.getItem().setMuestraBean(muestraRes);
		log.info("Getting result from muestra " + muestraRes.getName());
	}

	public void getResultColor() {
		log.info("Getting result from colors");
		newOrden.getItem().setColorBean(colorsBean.getResult());
	}

	public void getResultCliente() {
		log.info("Getting result from cliente");
		newOrden.getPedidoVenta().setClienteBean((clienteBean.getResult()));
	}

	public void pedidoNuevo(ActionEvent actionEvent) {

	}

	public ItemsBean getItemBean(ActionEvent actionEvent) {
		return itemBean;
	}

	public void setItemBean(ItemsBean itemBean) {
		this.itemBean = itemBean;
	}

	public List<OrdenProduccion> getFilteredOrdenProds() {
		return filteredOrdenProds;
	}

	public void setFilteredOrdenProds(List<OrdenProduccion> filteredOrdenProds) {
		this.filteredOrdenProds = filteredOrdenProds;
	}

	public List<OrdenProduccion> getOrdenesProd() {
		return ordenesProd;
	}

	public void setOrdenesProd(List<OrdenProduccion> ordenesProd) {
		this.ordenesProd = ordenesProd;
	}

	public IProduccionService getProduccionService() {
		return produccionService;
	}

	public void setProduccionService(IProduccionService produccionService) {
		this.produccionService = produccionService;
	}

	@PreDestroy
	public void predestroy() {
		log.info("OrdenVentasBenan  BEAN IS GOING TO BE DESTROYED");
	}

	public OrdenProduccion getNewOrden() {
		return newOrden;
	}

	public void setNewOrden(OrdenProduccion newOrden) {
		this.newOrden = newOrden;
	}

	public Item getSelectedItem() {
		return selectedItem;
	}

	public void setSelectedItem(Item selectedItem) {
		this.selectedItem = selectedItem;
	}

	public MuestrasBean getMuestraBean() {
		return muestraBean;
	}

	public void setMuestraBean(MuestrasBean muestraBean) {
		this.muestraBean = muestraBean;
	}

	public ClienteBean getClienteBean() {
		return clienteBean;
	}

	public void setClienteBean(ClienteBean clienteBean) {
		this.clienteBean = clienteBean;
	}

	public ColorsBean getColorsBean() {
		return colorsBean;
	}

	public void setColorsBean(ColorsBean colorsBean) {
		this.colorsBean = colorsBean;
	}

	public TipoMaterial[] getTiposMaterial() {
		return tiposMaterial;
	}

	public void setTiposMaterial(TipoMaterial[] tiposMaterial) {
		this.tiposMaterial = tiposMaterial;
	}

	public TipoMaterial getTipoMaterialSeleccionado() {
		return tipoMaterialSeleccionado;
	}

	public void setTipoMaterialSeleccionado(TipoMaterial tipoMaterialSeleccionado) {
		this.tipoMaterialSeleccionado = tipoMaterialSeleccionado;
	}

	public Date getCurrentDate() {
		return currentDate;
	}

	public void setCurrentDate(Date currentDate) {
		this.currentDate = currentDate;
	}

	public MenuModel getMenuModel() {
		return menuModel;
	}

	public void setMenuModel(MenuModel menuModel) {
		this.menuModel = menuModel;
	}

	public OrdenProduccion getSelectedOp() {
		return selectedOp;
	}

	public void setSelectedOp(OrdenProduccion selectedOp) {
		this.selectedOp = selectedOp;
	}

	public EstadoProduccion getEstadoFiltro() {
		return estadoFiltro;
	}

	public void setEstadoFiltro(EstadoProduccion estadoFiltro) {
		this.estadoFiltro = estadoFiltro;
	}

	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
	}

	public Periodo getPeriodo() {
		return periodo;
	}

	public void setPeriodo(Periodo periodo) {
		this.periodo = periodo;
	}

	public Periodo[] getPeriodos() {
		return periodos;
	}

	public void setPeriodos(Periodo[] periodos) {
		this.periodos = periodos;
	}

	public boolean isAddingItemToSalesOrder() {
		return addingItemToSalesOrder;
	}

	public void setAddingItemToSalesOrder(boolean addingItemToSalesOrder) {
		this.addingItemToSalesOrder = addingItemToSalesOrder;
	}

	public UserBean getUserBean() {
		return userBean;
	}

	public void setUserBean(UserBean userBean) {
		this.userBean = userBean;
	}

	public List<Color> getColores() {
		return colores;
	}

	public void setColores(List<Color> colores) {
		this.colores = colores;
	}

	public ItemsBean getItemBean() {
		return itemBean;
	}

}
